<?php

namespace app\common\middleware;

use app\admin\model\AdminModel;
use app\common\exception\ApiException;
use app\common\exception\Message;
use app\common\exception\Status;
use Closure;
use Exception;
use Firebase\JWT\BeforeValidException;
use Firebase\JWT\ExpiredException;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use Firebase\JWT\SignatureInvalidException;
use app\admin\model\AdminOptLogModel;
use app\user\model\User;
use think\facade\Config;
use think\Request;
use Throwable;

class Auth
{
    /**
     * 后台权限验证中间件
     *
     * @param Request $request
     * @param Closure $next
     * @return array|string|string[]
     * @throws ApiException
     */
    public function handle(Request $request, Closure $next)
    {
        // 获取请求路由信息
        $url = $request->url();
        $rootUrl = $request->rootUrl();
        // 替换请求中uri的前缀获取请求方法
        $rootUrlStr = str_replace('/', "", $rootUrl);
        // 定义一些不需要验证权限的接口
        $urlArr = [
            '/admin/login',  // 管理员登陆
            '/admin/info',
            '/admin/remoteAuth', //远程认证
            '/user/login',
        ];
        // 检测不需要验证的接口
        if (in_array($url, $urlArr)) {
            return $next($request);
        }
        
        header("Access-Control-Allow-Origin: *");
        $header = request()->header();
        if (empty($header['x-csrf-token']) || !isset($header['x-csrf-token'])) {
            return error("登陆过期！");
        }
        $HeaderToken = $header["x-csrf-token"];
        $key = 'locateMiNiToken';
        try {
            $info = JWT::decode($HeaderToken, new Key($key, 'HS256'));
            // $CacheToken = Cache::store('redis')->get("fm" . $info->uid . 'token');
            if ($rootUrlStr == 'admin') {
                $model = new AdminModel();
            } else {
                $model = new User();
            }
            $envToken = $model->where('token', $HeaderToken)->field('token')->find();
            if ($envToken == null) {
                return error('登录状态过期！');
            } else if ($envToken['token'] !== $HeaderToken) {
                return error('您已在其他设备登陆！');
            } else {
                if ($rootUrlStr == 'admin') {
                    $explode = explode('?', $url);
                    $opt = [
                        'itime' => time(),
                        'admin_id' => $info->admin_id,
                        'ip' => $_SERVER['REMOTE_ADDR'],
                        'url' => $explode[0],
                    ];
                    if (count($explode) > 1) {
                        array_push($opt, ['request' => $explode[1]]);
                    }
                    // 写入日志
                    (new AdminOptLogModel())->getInsert($opt);
                    $request->admin_id = $info->admin_id;
                } else {
                    $request->user_id = $info->user_id;
                }
            }
        } catch (SignatureInvalidException $e) { //签名不正确
            return error("签名不正确");
        } catch (BeforeValidException $e) { // 签名在某个时间点之后才能用
            return error("账号未到可用时间");
        } catch (ExpiredException $e) { // token过期
            return error('登录状态过期！');
        } catch (Exception $e) { //其他错误
            $res = [
                'file' => $e->getFile(),
                'message' => $e->getMessage(),
            ];
            return json(['message0' => $res]);
        } catch (Throwable $e) {
            return error(['message1' => $e->getMessage()]);
        }
        return $next($request);
    }
}
